package fr.bludwarf.skywarrior.evenements;

import fr.bludwarf.skywarrior.exceptions.ConstructionImpossibleException;
import fr.bludwarf.skywarrior.exceptions.IleInconnueException;
import fr.bludwarf.skywarrior.exceptions.RessourcesInsuffisantesException;
import fr.bludwarf.skywarrior.global.EtatMonde;
import fr.bludwarf.skywarrior.ile.Batiment;
import fr.bludwarf.skywarrior.ile.Construction;
import fr.bludwarf.skywarrior.ile.EtatIle;
import fr.bludwarf.skywarrior.ile.Ile;
import fr.bludwarf.skywarrior.joueur.EtatJoueur;
import fr.bludwarf.skywarrior.joueur.Ressources;
import fr.bludwarf.skywarrior.joueur.Unite;

public class CommencerConstruction extends Commencer<Construction, Ile>
{

	public CommencerConstruction(final EtatJoueur etatJoueur,
			final Construction construction)
	{
		super(construction, etatJoueur.tempsPourCollecter(construction
				.getCout()));
	}

	public Construction getConstruction()
	{
		return getProgression();
	}

	@Override
	public String toString()
	{
		return "Début de la construction de " + getConstruction().getUnite()
				+ " sur l'" + getConstruction().getIle();
	}

	// TODO : la pop de l'ile n'est consommé qu'à la fin mais est-ce qu'on peut
	// construire si le nombre d'habitants est insuffisant ?
	@Override
	public boolean estPossible(EtatMonde etatMonde) throws EvenementImpossible
	{
		final Ile ile = getConstruction().getIle();
		final EtatJoueur etatJoueur = getEtatJoueur(etatMonde);
		final EtatIle etatIle = etatJoueur.getEtatIle(ile);
		final Unite unite = getConstruction().getUnite();

		// Possibilité technologique
		if (!etatIle.peutConstruire(unite))
		{
			throw new EvenementImpossible(
					String.format(
						"Il ne sera jamais possible de construire %s pour des raisons technologiques ou à cause des règles",
						unite));
		}

		final Ressources stocks = etatJoueur.getStocks();
		final Ressources cout = getConstruction().getCout();

		if (!stocks.couvre(cout))
		{
			System.err.println("WARN : stocks insuffisants pour : " + this);

			// Evenement impossible ?
			if (!etatJoueur.getProduction(false).couvrira(cout))
			{
				throw new EvenementImpossible(
						"Il ne sera jamais possible de rassembler : " + cout);
			}

			return false;
		}

		final int popAfter = etatJoueur.getPop() + unite.getPop();
		if (popAfter > etatJoueur.getPopMax())
		{
			System.err.println("WARN : nombre d'unités max insuffisant pour : "
					+ this);

			// Evenement impossible ? : si on a pas prévu de construire de
			// nouvelles casernes
			if (!etatJoueur.aPrevuDeConstruire(Batiment.CASERNE))
			{
				throw new EvenementImpossible(
						"Il ne sera jamais possible d'avoir une pop max de "
								+ popAfter);
			}

			return false;
		}

		return true;
	}

	/**
	 * @return 
	 * 
	 */
	public EtatJoueur getEtatJoueur(EtatMonde etatMonde)
	{
		return etatMonde.getEtatJoueur(getProgression().getJoueur());
	}

	/**
	 * @return 
	 * @throws IleInconnueException 
	 * 
	 */
	public EtatIle getEtatIle(EtatMonde etatMonde) throws IleInconnueException
	{
		return etatMonde.getEtatIle(getProgression().getIle());
	}

	@Override
	public void commencerSur(EtatMonde etatMonde) throws Exception
	{
		// Consommation de ressource joueur
		final EtatJoueur etatJoueur = getEtatIle(etatMonde).getEtatJoueur();
		try
		{
			etatJoueur.consommer(getConstruction().getCout());
		} catch (final RessourcesInsuffisantesException e)
		{
			throw new ConstructionImpossibleException(
					"Impossible de construire " + getConstruction().getUnite(),
					e);
		}
	}

}
